﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
using NUnit.Framework;

namespace ServiceFramework.Tests
{
    [TestFixture]
    public class ServiceComponentListFixture
    {
        [Test]
        public void should_serialize_a_ServiceComponentList_using_XmlSerializer()
        {
            var myList = new ServiceComponentList();
            myList.Add(new HeartbeatServiceComponent(1));
            MemoryStream memoryStream = new MemoryStream();
            XmlSerializer s = new XmlSerializer(typeof(ServiceComponentList));
            TextWriter w = new StreamWriter(memoryStream);
            s.Serialize(w, myList);
            
            string test = Encoding.ASCII.GetString(memoryStream.GetBuffer(), 0, (int)memoryStream.Length);
            w.Close();

            TextWriter w2 = new StringWriter();
            w2.NewLine = "";
            s.Serialize(w2, myList);
            
            string t2 = w2.ToString();
        }

        [Test]
        public void should_use_ToXmlString_method_of_ServiceComponentList()
        {
            var myList = new ServiceComponentList();
            myList.Add(new HeartbeatServiceComponent(1));

            string expected =
                "<?xml version=\"1.0\" encoding=\"utf-8\"?><serviceComponents><component name=\"HeartbeatComponent\"><heartbeatFrequency beatsPerSecond=\"1\" /></component></serviceComponents>";
            string actual = myList.ToXmlString();
            Assert.AreEqual(expected, actual);
        }

        //[Test]
        //public void should_load_a_ServiceComponentList_from_an_xml_string()
        //{
        //    const string xmlString = "<?xml version=\"1.0\" encoding=\"utf-8\"?><serviceComponents><component name=\"HeartbeatComponent\"><heartbeatFrequency perSecond=\"1\" /></component></serviceComponents>";
        //    var myList = new ServiceComponentList();

        //    myList.LoadFromXmlString(xmlString);

        //    Assert.AreEqual(myList.Count, 1);
        //}
    }

    [XmlRoot("serviceComponents")]
    public class ServiceComponentList : List<IServiceComponent>, IXmlSerializable
    {
        public XmlSchema GetSchema()
        {
            return null;
        }

        public void ReadXml(XmlReader reader)
        {
            throw new System.NotImplementedException();
        }

        public void WriteXml(XmlWriter writer)
        {
            foreach (IServiceComponent component in this)
            {
                writer.WriteStartElement("component", "");
                writer.WriteAttributeString("name", component.Name);
                component.WriteXml(writer);
                writer.WriteEndElement();
            }
        }

        public string ToXmlString()
        {
            StringBuilder sb = new StringBuilder();
            TextWriter textWriter = new StringWriterWithEncoding(sb, Encoding.UTF8);

            XmlWriterSettings settings = new XmlWriterSettings();
            settings.NewLineHandling = NewLineHandling.None;

            XmlWriter writer = XmlWriter.Create(textWriter, settings);

            writer.WriteStartDocument();
            writer.WriteStartElement("serviceComponents");
            WriteXml(writer);
            writer.WriteEndElement();
            writer.WriteEndDocument();

            writer.Close();
            textWriter.Close();

            return sb.ToString();
        }
    }

    public class StringWriterWithEncoding : StringWriter
    {
        private readonly Encoding _encoding;

        public StringWriterWithEncoding(StringBuilder sb, Encoding encoding) : base(sb)
        {
            _encoding = encoding;
        }

        public override Encoding Encoding
        {
            get
            {
                return _encoding;
            }
        }
    }
}
